import zipfile

import os

import numpy as np


pwdCharset = ['`', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', ']', '{', '}', ';',
              ':', "'", '"', '\\', '|', ',', '<', '.', '>', '/', '?', 'a', 'A', 'b', 'B', 'c', 'C', 'd', 'D', 'e', 'E',
              'f', 'F', 'g', 'G', 'h', 'H', 'i', 'I', 'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N', 'o', 'O', 'p',
              'P', 'q', 'Q', 'r', 'R', 's', 'S', 't', 'T', 'u', 'U', 'v', 'V', 'w', 'W', 'x', 'X', 'y', 'Y', 'z', 'Z',
              '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
# 94\

CharsetInput = []


def gPwd(chST, lgth, rgth):
    while True:
        pl = int(np.random.random() * 100)
        if pl >= lgth and pl <= rgth:
            break

    pwd = ""

    chStLen = len(chST)

    for i in range(0, pl):
        while True:
            idx = int(np.random.random() * 100)
            if idx >= 0 and idx < chStLen:
                break
        pwd += chST[idx]

    return pwd


def dcryp(fileName, lLen, rLen, chST):
    fp = zipfile.ZipFile(fileName)

    count = 0

    while True:
        pwd = gPwd(chST, lLen, rLen)
        count += 1
        try:
            for file in fp.namelist():
                fp.extract(file, pwd=pwd.encode())
                os.rename(file, file.encode('cp437').decode('gbk'))
            print("%d Success! The password is %s" % (count, pwd))
            break
        except:
            print("%d %s no" % (count, pwd))


if __name__ == "__main__":
    fileName = input("请输入要破解的压缩包文件名:")
    choose = input("按1选择暴力破解。\n按2选择指定条件破解\n")

    if "1" == choose:
        leftLen = int(input("确定密码的长度范围:\n请输入密码的最小长度:"))
        rightLen = int(input("请输入密码的最大长度:"))
        dcryp(fileName, leftLen, rightLen, pwdCharset)
    elif "2" == choose:
        charSt = input("请输入密码中可能包含的字符:\n")
        for i in charSt:
            CharsetInput.append(i)
        leftLen = int(input("确定密码的长度范围:\n请输入密码的最小长度:"))
        rightLen = int(input("请输入密码的最大长度:"))
        dcryp(fileName, leftLen, rightLen, CharsetInput)
    else:
        print("无效输入！")